using System;
using System.Diagnostics;
using Yanesdk.System;
using Yanesdk.Draw;
using Yanesdk.Input;
using Yanesdk.Timer;
using Yanesdk.Math;
using Yanesdk.Ytl;
using Yanesdk.Sound;

namespace AdvEvaluator
{

    /// <summary>
    /// そのゲームで使う各種インスタンスよせ集め
    /// </summary>
    class GameSystem : IDisposable
    {

        #region プロパティ

        /// <summary>
        /// タスクコントローラ
        /// </summary>
        public TaskController TaskController { get; private set; }
        /// <summary>
        /// シーンコントローラ
        /// </summary>
        public SceneController<SceneName> SceneController { get; private set; }
        /// <summary>
        /// ウィンドウ
        /// </summary>
        public SDLWindow2DGl Window { get; private set; }
        /// <summary>
        /// 描画するスクリーン
        /// </summary>
        public Screen2DGl Screen
        {
            get { return Window.Screen; }
        }
        /// <summary>
        /// キーボードデバイス
        /// </summary>
        public KeyBoardInput Keyboard { get; private set; }
        /// <summary>
        /// マウスデバイス
        /// </summary>
        public MouseInput Mouse { get; private set; }
        /// <summary>
        /// FPS維持のためのタイマ
        /// </summary>
        public FpsTimer FpsTimer { get; private set; }
        /// <summary>
        /// 時間計測のためのタイマ
        /// </summary>
        public FixTimer FixTimer { get; private set; }
        /// <summary>
        /// テクスチャ読み込み
        /// </summary>
        public SmartTextureLoader SmartTextureLoader { get; private set; }
        /// <summary>
        /// サウンド読み込み
        /// </summary>
        public SmartSoundLoader SmartSoundLoader { get; private set; }
        /// <summary>
        /// フォント読み込み
        /// </summary>
        public SmartFontLoader SmartFontLoader { get; private set; }
        /// <summary>
        /// 乱数
        /// </summary>
        public Rand Rand { get; private set; }
        /// <summary>
        /// 終了後再起動するかどうか
        /// </summary>
        public bool Restart { get; set; }

        #endregion


        /// <summary>
        /// コンストラクタ
        /// </summary>
        public GameSystem()
        {
            // 変数の初期化
            this.TaskController = new TaskController();
            this.SceneController = new SceneController<SceneName>();
            this.Window = new SDLWindow2DGl();
            this.Keyboard = new KeyBoardInput();
            this.Mouse = new MouseInput();
            this.FpsTimer = new FpsTimer();
            this.FixTimer = new FixTimer();
            this.SmartFontLoader = new SmartFontLoader();
            this.SmartSoundLoader = new SmartSoundLoader();
            this.SmartTextureLoader = new SmartTextureLoader();
            this.Rand = new Rand();
            // ウィンドウ
            this.Window.SetCaption(Const.TITLE);
            this.Window.BeginScreenTest();
            this.Window.TestVideoMode(Const.WINDOW_WIDTH, Const.WINDOW_HEIGHT, 0);
            this.Window.EndScreenTest();
            this.Window.Screen.SetClearColor(255, 255, 255);
            this.Window.Screen.Blend = true;
            // 乱数
            this.Rand.Randomize();
            // FPS
            this.FpsTimer.Fps = Const.FPS;
            this.FpsTimer.Reset();
            // 再起動するかどうか
            this.Restart = false;
            // タスクコントローラの設定
            this.SceneController.TaskFactory = new SceneFactory(this);
            this.TaskController.AddTask(new Task.Timer(), (int)TaskPriority.Timer);
            this.TaskController.AddTask(new Task.Input(), (int)TaskPriority.Input);
            this.TaskController.AddTask(new Task.DrawBegin(), (int)TaskPriority.DrawBegin);
            this.TaskController.AddTask(this.SceneController, (int)TaskPriority.SceneController);
            this.TaskController.AddTask(new Task.DrawEnd(), (int)TaskPriority.DrawEnd);
            // 最初のシーンに飛ぶ
            this.SceneController.JumpScene(Const.INITIAL_SCENE);
        }

        /// <summary>
        /// メインループ
        /// </summary>
        public void Run()
        {
            // メインループ開始
            while (SDLFrame.PollEvent() == YanesdkResult.NoError && !this.SceneController.End) {
                // 指定したFPSになるように待つ
                this.FpsTimer.WaitFrame();
                if (this.FpsTimer.ToBeSkip) {
                    continue;
                }
                // FPSを表示
                ShowFps();
                // タスクの処理を優先度順(Priorityが小さい順)に実行
                this.TaskController.CallTask(this);
            }
        }

        /// <summary>
        /// FPSとCPU使用率をウィンドウのタイトルバーに表示する。
        /// リリース版のときは表示しない。
        /// </summary>
        [Conditional("DEBUG")]
        private void ShowFps()
        {
            this.Window.SetCaption(Const.TITLE + "   FPS : " + this.FpsTimer.RealFpsInt + "   CPU-Power:" + this.FpsTimer.CpuPower);
        }

        /// <summary>
        /// 後始末
        /// </summary>
        public void Dispose()
        {
            this.SceneController.Dispose();
            this.TaskController.Dispose();
            this.Mouse.Dispose();
            this.Keyboard.Dispose();
            this.SmartTextureLoader.Dispose();
            this.SmartSoundLoader.Dispose();
            this.SmartFontLoader.Dispose();
            this.Window.Dispose();
        }

    }

}
